using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using XUCore.Ddd.Domain;
using XUCore.NetCore.DynamicWebApi;
using XUCore.NetCore.FreeSql.Curd;
using XUCore.NetCore.FreeSql.Entity;
using XUCore.Paging;

namespace XUCore.NetCore.FreeSql
{
    /// <summary>
    /// CURD API 服务<para></para>
    /// 自动生成 Create、Update、Delete、SoftDelete、Get、GetList、GetPage 操作<para></para>
    /// 其中自动生成API：Create、Update、Delete、SoftDelete、Get、GetList、GetPage<para></para>
    /// 由于业务不同查询的条件不同，GetList、GetPage需要重写
    /// </summary>
    /// <typeparam name="TKey">主键类型</typeparam>
    /// <typeparam name="TEntity">数据库实体</typeparam>
    /// <typeparam name="TDto">返回实体</typeparam>
    /// <typeparam name="TCreateCommand">创建命令</typeparam>
    /// <typeparam name="TUpdateCommand">修改命令</typeparam>
    /// <typeparam name="TQueryCommand">查询列表命令</typeparam>
    /// <typeparam name="TQueryPageCommand">查询分页命令</typeparam>
    [DynamicWebApi]
    public abstract class AbstractCurdAppService<TKey, TEntity, TDto, TCreateCommand, TUpdateCommand, TQueryCommand, TQueryPageCommand> : IDynamicWebApi, IScoped
        where TEntity : class, IEntity<TKey>, new()
        where TDto : class, new()
        where TCreateCommand : CreateCommand
        where TUpdateCommand : UpdateCommand<TKey>
        where TQueryCommand : ListCommand
        where TQueryPageCommand : PageCommand
    {
        /// <summary>
        /// curd
        /// </summary>
        public CurdEntity<TKey, TEntity> curd;
        /// <summary>
        /// CURD API 服务<para></para>
        /// 自动生成 Create、Update、Delete、SoftDelete、Get、GetList、GetPage 操作<para></para>
        /// 其中自动生成API：Create、Update、Delete、SoftDelete、Get、GetList、GetPage<para></para>
        /// 由于业务不同查询的条件不同，GetList、GetPage需要重写
        /// </summary>
        /// <param name="serviceProvider"></param>
        public AbstractCurdAppService(IServiceProvider serviceProvider)
            : this(serviceProvider, serviceProvider.GetRequiredService<IFreeSql>())
        {
        }
        /// <summary>
        /// CURD API 服务<para></para>
        /// </summary>
        /// <param name="serviceProvider"></param>
        /// <param name="freeSql"></param>
        public AbstractCurdAppService(IServiceProvider serviceProvider, IFreeSql freeSql)
        {
            var mapper = serviceProvider.GetRequiredService<IMapper>();

            this.curd = new CurdEntity<TKey, TEntity>(freeSql, mapper);
        }

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost]
        public virtual async Task<TDto> CreateAsync([FromBody] TCreateCommand request, CancellationToken cancellationToken = default)
        {
            return await curd.CreateAsync<TCreateCommand, TDto>(request, cancellationToken);
        }
        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut]
        public virtual async Task<int> UpdateAsync([FromBody] TUpdateCommand request, CancellationToken cancellationToken = default)
        {
            return await curd.UpdateAsync<TUpdateCommand>(request, cancellationToken);
        }
        /// <summary>
        /// 物理删除数据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete]
        public virtual async Task<int> DeleteAsync([FromQuery] TKey id, CancellationToken cancellationToken = default)
            => await DeleteBatchAsync(new TKey[] { id }, cancellationToken);
        /// <summary>
        /// 物理删除数据
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete]
        public virtual async Task<int> DeleteBatchAsync([FromBody] TKey[] ids, CancellationToken cancellationToken = default)
            => await curd.DeleteAsync(ids, cancellationToken);
        /// <summary>
        /// 逻辑删除
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete]
        [DynamicMethod(IsVisible = false)]
        public virtual async Task<int> SoftDeleteAsync([FromQuery] TKey id, CancellationToken cancellationToken = default)
            => await SoftBatchDeleteAsync(new TKey[] { id }, cancellationToken);
        /// <summary>
        /// 逻辑删除
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete]
        [DynamicMethod(IsVisible = false)]
        public virtual async Task<int> SoftBatchDeleteAsync([FromBody] TKey[] ids, CancellationToken cancellationToken = default)
            => await curd.UpdateFieldAsync(ids, nameof(EntityFull<TKey, long?>.IsDeleted), true, cancellationToken);
        /// <summary>
        /// 根据id获取一条记录
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public virtual async Task<TDto> GetAsync(TKey id, CancellationToken cancellationToken = default)
            => await curd.GetAsync<TDto>(id, cancellationToken);
        /// <summary>
        /// 查询列表
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        public virtual async Task<List<TDto>> GetListAsync([FromQuery] TQueryCommand request, CancellationToken cancellationToken = default)
        {
            return await curd.GetListAsync<TDto>(where =>
                where
                    .LimitIf(request.Limit > 0, request.Limit)
                    .OrderByDescending(c => c.Id),
                cancellationToken);
        }
        /// <summary>
        /// 查询分页列表
        /// </summary>
        /// <param name="request"></param> 
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        public virtual async Task<PagedModel<TDto>> GetPageAsync([FromQuery] TQueryPageCommand request, CancellationToken cancellationToken = default)
        {
            return await curd.GetPageAsync<TDto>(where =>
                where
                    .OrderByDescending(c => c.Id),
                request.CurrentPage,
                request.PageSize,
                includeNestedMembers: true,
                defaultEndPage: false,
                cancellationToken);
        }
    }
}